/**
 * Created by Administrator on 2017/5/27.
 * Copyright 2017-2018 汉威.智慧环保事业部 Limited.
 * All rights reserved.
 */
package com.hw.one.collect.tasks.fairsense.client;

import com.hw.one.collect.po.FactorPo;
import com.hw.one.collect.po.SiteAirQualityPO;
import com.hw.one.collect.resource.BaseContext;
import com.hw.one.collect.tasks.fairsense.config.FairSenseConstants;
import com.hw.one.collect.tasks.fairsense.data.FairSenseDataService;
import com.hw.one.collect.util.ConvertUtil;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FairSenseClient {
    private static Logger log = LoggerFactory.getLogger(FairSenseClient.class);
    //存放ssid和ssid获取的日期
    private static final Map<String,String> TOKEN  = new HashMap<>();

    private FairSenseDataService fairSenseDataService =(FairSenseDataService) BaseContext.getService("fairSenseDataService");

    public void execute(Map<String, String> map) throws Exception {
        List<SiteAirQualityPO> list = getOneHourData();
        System.out.println("list = " + list);
        fairSenseDataService.insert(list);
    }

    public List<SiteAirQualityPO> getOneHourData(){
        //sids:1,2,3…
        // 站点id列表, 不传此参数则表示获取用户所能访问的全部
        Map<String,Object> params = new HashMap<>();

        Map<String,Object> cookies = new HashMap<>();
        cookies.put("username",FairSenseConstants.USERNAME);

        //判端token是否存在且有效
        if(StringUtils.isNotBlank(TOKEN.get("ssid"))){
            String cacheDateStr = TOKEN.get("createDate");
            try{
                Date cacheDate = DateUtils.parseDate(cacheDateStr,"yyyy-MM-dd HH");
                Calendar c = Calendar.getInstance();
                c.add(Calendar.HOUR_OF_DAY,-24);
                Date curDate = c.getTime();
                if(cacheDate.before(curDate)){
                    refreshToken();
                }
            }catch (Exception e){

            }
        }else{
            refreshToken();
        }
        cookies.put("ssid",TOKEN.get("ssid"));

        String result = post(FairSenseConstants.LATESTDATA_URI,params,cookies);
        if(StringUtils.isNotBlank(result)){
            try {
                List<Map<String,Object>> list = (List) ConvertUtil.json2List(result);
                List<SiteAirQualityPO> data = convertData(list);
                return data;
            } catch (Exception e) {
                e.printStackTrace();
                log.error("小时数据解析异常",e);
            }

        }
        return null;
    }

    private List<SiteAirQualityPO> convertData(List<Map<String,Object>> list){
//        List<Map<String,Object>> standardList = new ArrayList<>();
        List<SiteAirQualityPO> resultList = new ArrayList<>();
        for (Map<String,Object> map: list) {
            Map<String,Object> data = (Map<String, Object>) map.get("data");
            Map<String,Object> weatherData = (Map<String, Object>) map.get("weather_data");
            Map<String,Object> PM25 = (Map<String, Object>) data.get("PM2_5");
            Map<String,Object> SO2 = (Map<String, Object>) data.get("SO2");
            Map<String,Object> CO = (Map<String, Object>) data.get("CO");
            Map<String,Object> PM10 = (Map<String, Object>) data.get("PM10");
            Map<String,Object> O3 = (Map<String, Object>) data.get("O3");
            Map<String,Object> AQI = (Map<String, Object>) data.get("AQI");
            Map<String,Object> NO2 = (Map<String, Object>) data.get("NO2");
            String id = (String) map.get("id");
            String recordTime = (String) map.get("RecordTime");

            Map<String,Object> standard = new HashMap<>();

//            standard.put("SITECODE",id);
//            standard.put("SNCODE",id);
//            standard.put("DEVTYPE","004");
//            standard.put("MONITORTIME",recordTime);
//            standard.put("PM25",PM25.get("Value"));
//            standard.put("PM10",PM10.get("Value"));
//            standard.put("SO2",SO2.get("Value"));
//            standard.put("NO2",NO2.get("Value"));
//            standard.put("O3",O3.get("Value"));
//            standard.put("CO",CO.get("Value"));
//            standard.put("SO2IAQI",SO2.get("IAQI"));
//            standard.put("NO2IAQI",NO2.get("IAQI"));
//            standard.put("PM10IAQI",PM10.get("IAQI"));
//            standard.put("COIAQI",CO.get("IAQI"));
//            standard.put("O3_1IAQI",O3.get("IAQI"));
//            standard.put("PM25IAQI",PM25.get("IAQI"));
//            standard.put("AQI",AQI.get("Value"));
//            standard.put("AQILEVEL",AQI.get("Level"));
//            standard.put("HUM",weatherData.get("RH"));
//            standard.put("TEMP",weatherData.get("TEMP"));
//            standard.put("POLLUTANT",getPrimiaryPollution(PM25,SO2,CO,PM10,O3,NO2));

            SiteAirQualityPO siteAirQualityPO = new SiteAirQualityPO();
            siteAirQualityPO.setMONITORTIME(recordTime);
            siteAirQualityPO.setSITECODE(id);
            siteAirQualityPO.setSITENAME(id);
            siteAirQualityPO.setSITETYPECODE("004");
            siteAirQualityPO.setAQI(null == AQI.get("Value") ? "-1" : String.valueOf(AQI.get("Value")));
            siteAirQualityPO.setAQILEVEL(null == AQI.get("Level") ? "-" : String.valueOf(AQI.get("Level")));
            siteAirQualityPO.setAQILEVELTYPE(getAQILevelType(AQI.get("Level")));
            siteAirQualityPO.setPOLLUTANT(getPrimiaryPollution(PM25,SO2,CO,PM10,O3,NO2));
            siteAirQualityPO.setDATASOURCES("webapi");
            siteAirQualityPO.setCREATETIME(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            DecimalFormat df_1 = new DecimalFormat("###.#");
            siteAirQualityPO.setTEMP(null == weatherData.get("TEMP") ? "0" : df_1.format(Double.valueOf(weatherData.get("TEMP").toString())));
            siteAirQualityPO.setHUM(null == weatherData.get("RH") ? "0" : df_1.format(Double.valueOf(weatherData.get("RH").toString())));

            FactorPo PM10PO = new FactorPo();
            FactorPo PM25PO = new FactorPo();
            FactorPo SO2PO = new FactorPo();
            FactorPo NO2PO = new FactorPo();
            FactorPo COPO = new FactorPo();
            FactorPo O3PO = new FactorPo();

            PM10PO.setCONCENTRATION(PM10.get("Value") == null ? "0" : String.valueOf(PM10.get("Value")));
            PM10PO.setIAQI(PM10.get("IAQI") == null ? "0" : String.valueOf(PM10.get("IAQI")));
            PM10PO.setSTATE(null == PM10.get("Value") ? "Z" : "N");

            PM25PO.setCONCENTRATION(PM25.get("Value") == null ? "0" : String.valueOf(PM25.get("Value")));
            PM25PO.setIAQI(PM25.get("IAQI") == null ? "0" : String.valueOf(PM25.get("IAQI")));
            PM25PO.setSTATE(null == PM25.get("Value") ? "Z" : "N");

            SO2PO.setCONCENTRATION(SO2.get("Value") == null ? "0" : String.valueOf(SO2.get("Value")));
            SO2PO.setIAQI(SO2.get("IAQI") == null ? "0" : String.valueOf(SO2.get("IAQI")));
            SO2PO.setSTATE(null == SO2.get("Value") ? "Z" : "N");

            NO2PO.setCONCENTRATION(NO2.get("Value") == null ? "0" : String.valueOf(NO2.get("Value")));
            NO2PO.setIAQI(NO2.get("IAQI") == null ? "0" : String.valueOf(NO2.get("IAQI")));
            NO2PO.setSTATE(null == NO2.get("Value") ? "Z" : "N");

            COPO.setCONCENTRATION(CO.get("Value") == null ? "0" : String.valueOf(CO.get("Value")));
            COPO.setIAQI(CO.get("IAQI") == null ? "0" : String.valueOf(CO.get("IAQI")));
            COPO.setSTATE(null == CO.get("Value") ? "Z" : "N");

            O3PO.setCONCENTRATION(O3.get("Value") == null ? "0" : String.valueOf(O3.get("Value")));
            O3PO.setIAQI(O3.get("IAQI") == null ? "0" : String.valueOf(O3.get("IAQI")));
            O3PO.setSTATE(null == O3.get("Value") ? "Z" : "N");
            siteAirQualityPO.setPM10(PM10PO);
            siteAirQualityPO.setPM25(PM25PO);
            siteAirQualityPO.setSO2(SO2PO);
            siteAirQualityPO.setNO2(NO2PO);
            siteAirQualityPO.setCO(COPO);
            siteAirQualityPO.setO3(O3PO);

            resultList.add(siteAirQualityPO);
        }

        return resultList;
    }

    private String getAQILevelType(Object AQILevel) {
        if (null == AQILevel || !isInteger(String.valueOf(AQILevel))) {
            return "-";
        }
        int level = Integer.valueOf(String.valueOf(AQILevel));
        switch (level) {
            case 1:
                return "优";
            case 2:
                return "良";
            case 3:
                return "轻度污染";
            case 4:
                return "中度污染";
            case 5:
                return "重度污染";
            case 6:
                return "严重污染";
            default:
                return "-";
        }



    }

    /**
     * 判断传入字符串是否是整数
     *
     * @param str
     * @return
     */
    public boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        Matcher isInt = pattern.matcher(str);
        if (isInt.matches()) {
            return true;
        }
        return false;
    }


    private String getPrimiaryPollution(Map<String, Object> PM25, Map<String, Object> SO2, Map<String, Object> CO,
                                Map<String, Object> PM10, Map<String, Object> O3, Map<String, Object> NO2) {
        boolean isPM25 = BooleanUtils.toBoolean((String) PM25.get("isPri"));
        boolean isSO2 =  BooleanUtils.toBoolean((String)SO2.get("isPri"));
        boolean isCO =  BooleanUtils.toBoolean((String)CO.get("isPri"));
        boolean isPM10 =  BooleanUtils.toBoolean((String) PM10.get("isPri"));
        boolean isO3 =  BooleanUtils.toBoolean((String)O3.get("isPri"));
        boolean isNO2 =  BooleanUtils.toBoolean((String) NO2.get("isPri"));
        if(isPM25){
            return "PM2.5";
        }
        if(isSO2){
            return "SO2";
        }
        if(isCO){
            return "CO";
        }
        if(isPM10){
            return "PM10";
        }
        if(isO3){
            return "O3";
        }
        if(isNO2){
            return "NO2";
        }
        return "";
    }

    private void refreshToken(){
        String token = getToken();
        if(StringUtils.isNotBlank(token)){
            TOKEN.put("ssid",token);
            String createDate = new SimpleDateFormat("yyyy-MM-dd HH").format(new Date());
            TOKEN.put("createDate",createDate);
        }
    }

    public String getToken(){
        Map<String,Object> params = new HashMap<>();
        params.put("username",FairSenseConstants.USERNAME);
        params.put("password",FairSenseConstants.PASSWORD);
        String result = post(FairSenseConstants.AUTHEN_URI,params);
        if(StringUtils.isNotBlank(result)){
            try {
                Map<String,Object> map = ConvertUtil.json2Map(result);
                return (String) ((Map<String,Object>)map.get("user")).get("ssid");
            }catch (Exception e){
                log.error("token获取异常",e);
            }
        }
        return null;
    }


    public String post(String uri,Map<String,Object> params){
        return post(uri,params,null);
    }

    public String post(String uri, Map<String, Object> params, Map<String, Object> cookies) {
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try {
            client = HttpClients.createDefault();
            HttpPost post = new HttpPost(uri);
            if (null != params && !params.isEmpty()) {
                List<NameValuePair> formData = wrapParams(params);
                HttpEntity requestEntity = new UrlEncodedFormEntity(formData, "UTF-8");
                post.setEntity(requestEntity);
            }

            if (null != cookies && !cookies.isEmpty()) {
                String cookieStore = wrapCookiesStr(cookies);
                post.addHeader("Cookie", cookieStore);
            }
            response = client.execute(post);
            HttpEntity responseEntity = response.getEntity();
            String result = EntityUtils.toString(responseEntity);
            log.info("泛测数据拉取结果：" + result);
            return result;
        } catch (Exception e) {
            log.error("泛测数据拉取异常", e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                if (client != null) {
                    client.close();
                }
            } catch (IOException e) {
                log.error("泛测client关闭异常", e);
            }

        }
        return null;
    }

    private static List<NameValuePair> wrapParams(Map<String,Object> map) {
        List<NameValuePair> param = new ArrayList<>();
        Iterator<Map.Entry<String,Object>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String,Object> entry = it.next();
            param.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue()) ));
        }
        return param;
    }

    private static CookieStore wrapCookies(Map<String,Object> map){
        CookieStore cookieStore = new BasicCookieStore();
        Iterator<Map.Entry<String,Object>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String,Object> entry = it.next();
            cookieStore.addCookie(new BasicClientCookie(entry.getKey(), String.valueOf(entry.getValue())) {
            });
        }
        return cookieStore;
    }
    private static String wrapCookiesStr(Map<String,Object> map){
        String cookies="";
        Iterator<Map.Entry<String,Object>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String,Object> entry = it.next();
            cookies  += entry.getKey()+"=" + String.valueOf(entry.getValue())+";";
        }
        return cookies;
    }

}
